package prototipo.server.logic.transaction;

import java.math.BigDecimal;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import prototipo.server.logic.exception.ExceptionLogic;

public abstract class Transaction implements TransactionIF {

	private long id;
	private GregorianCalendar dateCreate;
	private GregorianCalendar dateLatter;
	private List<ItemPayIF> listItens;
	private List<PaymentIF> payments;

	/**
	 * @param dateLatter
	 * @param listItens
	 * @param payment
	 * @throws ExceptionLogic
	 */
	public Transaction(GregorianCalendar dateLatter, List<ItemPayIF> listItens,
			List<PaymentIF> payments) throws ExceptionLogic {
		super();
		GregorianCalendar dateNow = new GregorianCalendar();
		dateNow.setTime(new Date());
		this.setDateCreate(dateNow);
		this.setDateLatter(dateLatter);
		this.setListItens(listItens);
		this.setPayments(payments);
	}

	/**
	 * @return the id
	 */
	public long getId() {
		return id;
	}

	/**
	 * @param id
	 *            the id to set
	 */
	public void setId(long id) {
		this.id = id;
	}

	/**
	 * @return the dateCreate
	 */
	public GregorianCalendar getDateCreate() {
		return dateCreate;
	}

	/**
	 * @param dateCreate
	 *            the dateCreate to set
	 * @throws ExceptionLogic
	 */
	public void setDateCreate(GregorianCalendar dateCreate)
			throws ExceptionLogic {
		if (dateCreate == null)
			throw new ExceptionLogic("Data vazia.", new Throwable(
					"Calendar is null."));
		this.dateCreate = dateCreate;
	}

	/**
	 * @return the dateLatter
	 */
	public GregorianCalendar getDateLatter() {
		return dateLatter;
	}

	/**
	 * @param dateLatter
	 *            the dateLatter to set
	 * @throws ExceptionLogic
	 */
	public void setDateLatter(GregorianCalendar dateLatter)
			throws ExceptionLogic {
		if (dateLatter == null)
			throw new ExceptionLogic("Data vazia.", new Throwable(
					"Calendar is null."));
		this.dateLatter = dateLatter;
	}

	/**
	 * @return the listItens
	 */
	public List<ItemPayIF> getListItens() {
		return listItens;
	}

	/**
	 * @throws ExceptionLogic
	 * @param listItens
	 *            the listItens to set
	 * @throws
	 */
	public void setListItens(List<ItemPayIF> newListItens)
			throws ExceptionLogic {
		if (newListItens == null || newListItens.size() == 0)
			throw new ExceptionLogic("Lista de itens vazia.", new Throwable(
					"Itens' list is null."));
		if (validateListItem(newListItens)) {
			if (this.payments != null) {
				BigDecimal sum = new BigDecimal(0);
				for (ItemPayIF item : newListItens) {
					sum = sum.add(item.getValue().getValue().multiply(
							new BigDecimal(item.getAmount())));
				}
				BigDecimal sumpay = new BigDecimal(0);
				for (PaymentIF pay : this.payments) {
					sumpay = sumpay.add(pay.getValue().getValue());
				}
				if (sum.compareTo(sumpay) != 0)
					throw new ExceptionLogic(
							"Valor do pagamento nao confere com o valor da transacao.",
							new Throwable("Comparation is not igual of zero."));

			}
			this.listItens = newListItens;
		}
	}

	protected abstract boolean validateListItem(List<ItemPayIF> newListItens) throws ExceptionLogic;

	/**
	 * @return the payment
	 */
	public List<PaymentIF> getPayment() {
		return payments;
	}

	/**
	 * @param payment
	 *            the payment to set
	 * @throws Exception
	 */
	public void setPayments(List<PaymentIF> payments) throws ExceptionLogic {
		if (payments == null || payments.size() == 0)
			throw new ExceptionLogic("Lista de pagamentos vazia.",
					new Throwable("Payments' list is null."));
		List<ItemPayIF> list = this.getListItens();
		BigDecimal sum = new BigDecimal(0);
		for (ItemPayIF item : list) {
			sum = sum.add(item.getValue().getValue().multiply(
					new BigDecimal(item.getAmount())));
		}
		BigDecimal sumpay = new BigDecimal(0);
		for (PaymentIF pay : payments) {
			sumpay = sumpay.add(pay.getValue().getValue());
		}
		if (sum.compareTo(sumpay) != 0)
			throw new ExceptionLogic(
					"Valor do pagamento nao confere com o valor da transacao.",
					new Throwable("Comparation is not igual of zero."));

		this.payments = payments;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public final int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + (int) (id ^ (id >>> 32));
		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public final boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (!(obj instanceof Transaction))
			return false;
		Transaction other = (Transaction) obj;
		if (id != other.id)
			return false;
		return true;
	}

}
